package systemf;



class Interpreter(verbose:Boolean)  { self: Interpreter with TypedLambdaParser with Desugar with TypeChecker with Evaluator  with SubstitutionProvider=>


  def eval(line: String):LTerm = {
      val canontree=parse(line);
      typeCheck(canontree); //throws typeExc so we only eval if type is ok
      eval(canontree);
  }
  
  def parse(line: String):LTerm = {
    if (verbose)   println("srccode = "+ line)
    val rawtree = parseString(line) getOrElse exit(1)
    if (verbose)   println("rawparse= "+ rawtree.toString_(new Context(Nil)))
    val canontree = desugar(rawtree)
    if (verbose) { println("   parse= " + canontree.toString_(new Context(Nil)))
                   println("   AST  = " + canontree.toString)
                 }
    canontree
  }
  
  
  
  def typeCheck(canontree: LTerm) =  {
  
    val ty = typeOf(canontree)
    if (verbose) println("       :: "+ty.toString_(new Context(Nil)))
    ty
  }
  
  def eval(canontree: LTerm):LTerm =  {
    val value = evaluate(canontree)
    if (verbose) println(" =======> " + value .toString_(new Context(Nil)))
    value
  }
}

trait LambdaParser {

  def parseString(str: String) : Option[LTerm]
}
trait Desugar {
  type RawTerm
  def desugar(t: LTerm):LTerm
}
case class TypeExc(message:String) extends Exception(message)
trait TypeChecker { 

  def typeOf(t: LTerm) :LType

}
trait Evaluator {

  def evaluate(t: LTerm) : LTerm  
  case class NoReductionPossibleExc extends Exception
}

